package com.ibeeking.found.msg.rest.service.impl;

import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.entity.DictDTO;
import com.ibeeking.found.common.enums.DictTypeEnum;
import com.ibeeking.found.common.enums.LanguageI18CodeEnum;
import com.ibeeking.found.common.enums.member.MemberSexEnum;
import com.ibeeking.found.common.utils.UserUtils;

import com.ibeeking.found.msg.api.common.dto.TagsDefineDTO;
import com.ibeeking.found.msg.api.common.query.FeignTagsDefineQuery;
import com.ibeeking.found.msg.api.feign.MsgMemberBClient;
import com.ibeeking.gmc.global.api.feign.GlobalDictFeignClient;

import com.ibeeking.found.msg.api.common.query.SubscribeQuery;
import com.ibeeking.found.msg.rest.service.IWxMpFansService;
import com.ibeeking.found.msg.rest.service.IWxMpFansTagsService;
import com.ibeeking.found.msg.rest.service.IOpenService;
import com.ibeeking.found.msg.service.common.bo.WxMpFansBO;
import com.ibeeking.found.msg.service.common.bo.WxMpFansIdBO;
import com.ibeeking.found.msg.service.common.bo.WxMpFansTagsBO;
import com.ibeeking.found.msg.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.msg.service.common.dos.WxMpFansDO;
import com.ibeeking.found.msg.service.common.param.WxMpFansParam;
import com.ibeeking.found.msg.service.common.query.WxMpFansPageQuery;
import com.ibeeking.found.msg.service.common.vo.WxMpFansPageVO;
import com.ibeeking.found.msg.service.common.vo.WxMpFansVO;
import com.ibeeking.found.msg.service.common.vo.WxMpFansTagsVO;
import com.ibeeking.found.msg.service.mapper.WxMpFansMapper;
import com.ibeeking.nematos.constants.enums.LogClassifyEnum;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.DataUtils;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.date.DateUtil;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jodd.util.StringUtil;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.open.api.WxOpenMpService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName WxMpFansServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2020-12-30 14:12
 **/
@Service
public class WxMpFansServiceImpl extends ServiceImpl<WxMpFansMapper, WxMpFansDO> implements IWxMpFansService {

    @Resource
    private IOpenService wxOpenServiceImpl;
    @Resource
    private WxMpFansMapper wxMpFansMapper;
    @Resource
    private GlobalDictFeignClient globalDictFeignClient;
    @Resource
    private MsgMemberBClient memberFeignBClient;
    @Resource
    private IWxMpFansTagsService mpFansTagsServiceImpl;
    @Resource
    private RedisUtils redisUtils;


    @Override
    public Page<WxMpFansPageVO> pageList(WxMpFansPageQuery query) {
        LambdaQueryWrapper<WxMpFansDO> queryWrapper = wrapperQueryCondition(query);
        Page<WxMpFansDO> mpFansPage = wxMpFansMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), queryWrapper);
        Page<WxMpFansPageVO> wxMpfansResultVO = BeanUtil.convertPage(mpFansPage, WxMpFansPageVO.class);
        LogUtils.info("====wxMpfansResultVO:{}======= ", JsonUtils.toJsonStr(wxMpfansResultVO));
        if (!Collections3.isEmpty(wxMpfansResultVO.getRecords())) {
            //查询字典
            Map<String, String> wxMpSceneTypeMap = new HashMap<>();
            ResponseResult<List<DictDTO>> sceneTypes = globalDictFeignClient.queryDictByType(DictTypeEnum.MP_SCENE_TYPE.getValue());
            if (!Collections3.isEmpty(sceneTypes.getData())) {
                wxMpSceneTypeMap = sceneTypes.getData().parallelStream().collect(Collectors.toMap(DictDTO::getValue, DictDTO::getLabel, (s, a) -> a));
            }
            List<WxMpFansPageVO> wxMpFansPageRecords = wxMpfansResultVO.getRecords();
            //查询标签
            List<WxMpFansTagsBO> wxMpFansTagsBOS = mpFansTagsServiceImpl.queryTagsIdsByFansIds(query.getAppId(), wxMpFansPageRecords.parallelStream().map(WxMpFansPageVO::getId).collect(Collectors.toList()));

            Map<Long, String> wxMpFansTagsMap = Collections3.emptyMap();
            Map<Long, List<WxMpFansTagsBO>> fansTagsGroup = Collections3.emptyMap();
            if (!Collections3.isEmpty(wxMpFansTagsBOS)) {
                FeignTagsDefineQuery feignTagsDefineQuery = new FeignTagsDefineQuery();
                feignTagsDefineQuery.setIdList(wxMpFansTagsBOS.parallelStream().map(WxMpFansTagsBO::getTagsId).distinct().collect(Collectors.toList()));
                ResponseResult<List<TagsDefineDTO>> responseResult = memberFeignBClient.effectiveManualList(feignTagsDefineQuery);
                if (!Collections3.isEmpty(responseResult.getData())) {
                    wxMpFansTagsMap = responseResult.getData().parallelStream().collect(Collectors.toMap(TagsDefineDTO::getId, TagsDefineDTO::getName, (s, a) -> a));
                }
                fansTagsGroup = wxMpFansTagsBOS.parallelStream().collect(Collectors.groupingBy(WxMpFansTagsBO::getFansId));
            }
            Map<String, String> finalSceneTypeMap = wxMpSceneTypeMap;
            for (WxMpFansPageVO wxMpFansPageVO : wxMpFansPageRecords) {
                List<WxMpFansTagsBO> wxMpFansTagsBOS1 = fansTagsGroup.get(wxMpFansPageVO.getId());
                if (!Collections3.isEmpty(wxMpFansTagsBOS1)) {
                    StringBuffer sb = new StringBuffer("");
                    for (WxMpFansTagsBO wxMpFansTagsBO : wxMpFansTagsBOS1) {
                        if (0 == sb.length()) {
                            Optional.ofNullable(wxMpFansTagsMap.get(wxMpFansTagsBO.getTagsId())).ifPresent(sb::append);
                        } else {
                            Optional.ofNullable(wxMpFansTagsMap.get(wxMpFansTagsBO.getTagsId())).ifPresent(tagsName -> {
                                sb.append(",").append(tagsName);
                            });
                        }
                    }
                    wxMpFansPageVO.setTags(sb.toString());
                }
                if(StringUtil.isNotEmpty(wxMpFansPageVO.getLanguage())){
                    wxMpFansPageVO.setLanguage(LanguageI18CodeEnum.getNameByCode(wxMpFansPageVO.getLanguage()));
                }
                if(wxMpFansPageVO.getSex() !=null) {
                    wxMpFansPageVO.setSexName(MemberSexEnum.getDescByCode(wxMpFansPageVO.getSex()));
                }
                if(StringUtils.isNotBlank(wxMpFansPageVO.getSubscribeScene())) {
                    wxMpFansPageVO.setSubscribeSceneName(finalSceneTypeMap.get(wxMpFansPageVO.getSubscribeScene()));
                }
            }
        }
        LogUtils.info("====wxMpfansResultVO:{}======= ", JsonUtils.toJsonStr(wxMpfansResultVO));
        return wxMpfansResultVO;
    }

    @Override
    public Boolean syncFansFromWx(String appId) {
        try {
            Long userId = UserUtils.getUserId();
            if(userId == null) userId = 9999L; //如果系统任务同步
            if (redisUtils.tryLock(appId, 10, 6)) {
                Object obj = redisUtils.get(RedisKeyConstant.MP_SYNC + appId);
                LogUtils.info("====appid:{},obj:{}======= ", appId, obj);
                if (null != obj) {
                    return false;
                } else {
                    syncFans(appId);
                    redisUtils.set(RedisKeyConstant.MP_SYNC + appId, userId, RedisKeyConstant.HOUR);
                    return true;
                }
            } else {
                return false;
            }
        } finally {
            redisUtils.unlock(appId);
        }
    }

    private Boolean syncFans(String appId) {
        try {
            //第一阶段方案
            List<String> addFansOpenIds = new ArrayList<>();
            //先查询当前存在的用户openId
            LambdaQueryWrapper<WxMpFansDO> queryWrapper = new LambdaQueryWrapper<>(WxMpFansDO.class);
            queryWrapper.select(WxMpFansDO::getOpenId);
            List<Object> fansOpenIdsObjects = wxMpFansMapper.selectObjs(queryWrapper);

            List<String> fansOpenIds = Collections3.emptyList();
            if (Collections3.isNotEmpty(fansOpenIdsObjects)) {
                fansOpenIds = JsonUtils.jsonToList(fansOpenIdsObjects, String.class);
            }
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有发现授权公众号！");
            if(StringUtils.isBlank(appId)) {
                appId = wxOpenMpService.getWxMpConfigStorage().getAppId();
            }
            WxMpUserService wxMpUserService = wxOpenMpService.getUserService();
            if(wxMpUserService == null) throw new BusinessException("没有发现授权公众号！");

            //同步openId数据
            Boolean flag = true;
            String nextFansOpenId = null;
            int i = 0;
            while (flag && i < 3) {
                WxMpUserList wxMpUserList = null;
                try {
                    wxMpUserList = wxMpUserService.userList(nextFansOpenId);
                } catch (WxErrorException e) {
                    LogUtils.error(LogClassifyEnum.SYSTEM_LOG, "批量获取粉丝openId错误", e);
                    ++i;
                    continue;
                }
                if (!Collections3.isEmpty(wxMpUserList.getOpenids())) {
                    //取差集
                    addFansOpenIds.addAll(Collections3.difference(wxMpUserList.getOpenids(), fansOpenIds));
                }
                nextFansOpenId = wxMpUserList.getNextOpenid();
                if (StringUtils.isBlank(nextFansOpenId)) {
                    flag = false;
                }
            }
            List<WxMpFansDO> savesWxMpFansDOS = new ArrayList<>();
            //分批次获取新增的粉丝数据
            List<List<String>> fansOpenIdsGroups = DataUtils.groupList(addFansOpenIds, 100);

            for (List<String> fansOpenIdsGroup : fansOpenIdsGroups) {
                List<WxMpUser> wxMpUsers = null;
                try {
                    wxMpUsers = wxMpUserService.userInfoList(fansOpenIdsGroup);

                } catch (WxErrorException e) {
                    LogUtils.error(LogClassifyEnum.SYSTEM_LOG, "批量获取粉丝信息错误", e);
                    continue;
                }
                if (Collections3.isNotEmpty(wxMpUsers)) {
                    for (int j = 0; j < wxMpUsers.size(); j++) {
                        WxMpUser wxMpUser = wxMpUsers.get(j);
                        WxMpFansDO wxMpFansDO = new WxMpFansDO();
                        wxMpFansDO.setAppId(appId);
                        wxMpFansDO.setCreateBy(UserUtils.getUserId());
                        wxMpFansDO.setSubscribe(wxMpUser.getSubscribe() ? 1 : 0);
                        wxMpFansDO.setOpenId(StringUtils.isNotBlank(wxMpUser.getOpenId()) ? wxMpUser.getOpenId() : "");
                        if (wxMpUser.getSubscribe()) {
                            wxMpFansDO.setUnionId(StringUtils.isNotBlank(wxMpUser.getUnionId()) ? wxMpUser.getUnionId() : "");
                            //wxMpFansDO.setNickName(wxMpUser.getNickname());
//                            wxMpFansDO.setSex(wxMpUser.getSex());
//                            wxMpFansDO.setCountry(wxMpUser.getCountry());
//                            wxMpFansDO.setProvince(wxMpUser.getProvince());
//                            wxMpFansDO.setCity(wxMpUser.getCity());
                            wxMpFansDO.setLanguage(wxMpUser.getLanguage());
                            //wxMpFansDO.setHeadImgurl(wxMpUser.getHeadImgUrl());
                            wxMpFansDO.setSubscribeTime(DateUtil.longToLocalDateTime(wxMpUser.getSubscribeTime()));
                            wxMpFansDO.setRemark(StringUtils.isNotBlank(wxMpUser.getRemark()) ? wxMpUser.getRemark() : "");
                            Optional.ofNullable(wxMpUser.getGroupId()).ifPresent(groupId -> {
                                wxMpFansDO.setGroupId(groupId);
                            });
                            wxMpFansDO.setSubscribeScene(wxMpUser.getSubscribeScene());
                            Optional.ofNullable(wxMpUser.getQrScene()).ifPresent(qrScene -> {
                                wxMpFansDO.setQrScene(qrScene);
                            });
                            Optional.ofNullable(wxMpUser.getQrSceneStr()).ifPresent(qrSceneStr -> {
                                wxMpFansDO.setQrSceneStr(qrSceneStr);
                            });
                            wxMpFansDO.setCreateTime(LocalDateTime.now());
                            wxMpFansDO.setModifyTime(LocalDateTime.now());
                            savesWxMpFansDOS.add(wxMpFansDO);
                        }
                    }
                }

                if (savesWxMpFansDOS.size() >= 900) {
                    wxMpFansMapper.insertBatchSomeColumn(savesWxMpFansDOS);
                    savesWxMpFansDOS = new ArrayList<>();
                }

            }
            if (Collections3.isNotEmpty(savesWxMpFansDOS)) {
                return wxMpFansMapper.insertBatchSomeColumn(savesWxMpFansDOS) >0;
            }
        } finally {
            redisUtils.del(RedisKeyConstant.MP_SYNC + appId);
        }
        return false;
    }


    @Override
    public Boolean export(WxMpFansPageQuery wxMpFansPageQuery) {
        //导出
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(WxMpFansParam param) {
        if (StringUtils.isNotBlank(param.getRemark())) {
            WxMpFansVO wxMpFansVO = getBean().view(param.getAppId(), param.getId());
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有发现授权公众号！");
            try {
                WxMpUserService wxMpUserService = wxOpenMpService.getUserService();
                if(wxMpUserService == null) throw new BusinessException("没有发现授权公众号！");
                wxMpUserService.userUpdateRemark(wxMpFansVO.getOpenId(), param.getRemark());
            } catch (WxErrorException e) {
                LogUtils.error("更新粉丝备注失败", e);
                return false;
            }
            wxMpFansVO.setRemark(param.getRemark());
            WxMpFansDO wxMpFansDO = BeanUtil.convertBean(param, WxMpFansDO.class);
            wxMpFansDO.setModifyTime(LocalDateTime.now());
            wxMpFansMapper.updateById(wxMpFansDO);
        }

        //更新标签
        mpFansTagsServiceImpl.modifyTags(param.getAppId(), param.getId(), param.getTagsList());
        return true;
    }

    @Override
    public WxMpFansVO view(String appId, Long id) {
        WxMpFansDO wxMpFansDO = wxMpFansMapper.selectById(id);
        WxMpFansVO wxMpFansVO = JsonUtils.fromJson(wxMpFansDO, WxMpFansVO.class);
        ResponseResult<DictDTO> scene = globalDictFeignClient.queryDictLable(DictTypeEnum.MP_SCENE_TYPE.getValue(), wxMpFansVO.getSubscribeScene());
        wxMpFansVO.setSexName(MemberSexEnum.getDescByCode(wxMpFansVO.getSex()));
        wxMpFansVO.setSubscribeSceneName(null == scene.getData() ? "" : scene.getData().getLabel());
        //查询标签
        List<WxMpFansTagsBO> wxMpFansTagsBos = mpFansTagsServiceImpl.queryTagsIdsByFansIds(appId, Arrays.asList(id));
        if (!Collections3.isEmpty(wxMpFansTagsBos)) {
            FeignTagsDefineQuery query = new FeignTagsDefineQuery();
            query.setIdList(wxMpFansTagsBos.parallelStream().map(WxMpFansTagsBO::getTagsId).distinct().collect(Collectors.toList()));
            ResponseResult<List<TagsDefineDTO>> responseResult = memberFeignBClient.effectiveManualList(query);
            Optional.ofNullable(responseResult.getData()).ifPresent(l -> wxMpFansVO.setTagsVos(JsonUtils.jsonToList(l, WxMpFansTagsVO.class)));
        }
        return wxMpFansVO;
    }

    @Override
    public List<Long> queryFansList(WxMpFansPageQuery query) {
        if (StringUtils.isNotBlank(query.getSubscribeStartTime()) || StringUtils.isNotBlank(query.getSubscribeEndTime())) {
            if (StringUtils.isBlank(query.getSubscribeStartTime())) {
                query.setSubscribeStartTime(LocalDate.now().toString());
            }
            if (StringUtils.isBlank(query.getSubscribeEndTime())) {
                query.setSubscribeEndTime(LocalDate.now().toString());
            }
        }

        if (StringUtils.isNotBlank(query.getCancelSubscribeStartTime()) || StringUtils.isNotBlank(query.getCancelSubscribeEndTime())) {
            if (StringUtils.isBlank(query.getCancelSubscribeStartTime())) {
                query.setCancelSubscribeStartTime(LocalDate.now().toString());
            }

            if (StringUtils.isBlank(query.getCancelSubscribeStartTime())) {
                query.setCancelSubscribeEndTime(LocalDate.now().toString());
            }
        }
        LambdaQueryWrapper<WxMpFansDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(BaseDO::getCreateTime)
                .eq(WxMpFansDO::getAppId, query.getAppId())
                .eq(null != query.getSubscribe(), WxMpFansDO::getSubscribe, query.getSubscribe())
                .eq(StringUtils.isNotBlank(query.getOpenId()), WxMpFansDO::getOpenId, query.getOpenId())
                .eq(StringUtils.isNotBlank(query.getUnionId()), WxMpFansDO::getUnionId, query.getUnionId())
                .eq(null != query.getSex(), WxMpFansDO::getSex, query.getSex())
                .eq(null != query.getGroupId(), WxMpFansDO::getGroupId, query.getGroupId())
                .eq(StringUtils.isNotBlank(query.getSubscribeScene()), WxMpFansDO::getSubscribeScene, query.getSubscribeScene())
                .like(StringUtils.isNotBlank(query.getNickName()), WxMpFansDO::getNickName, query.getNickName())
                .between(StringUtils.isNotBlank(query.getSubscribeStartTime()), WxMpFansDO::getSubscribeTime, query.getSubscribeStartTime(), query.getSubscribeEndTime())
                .between(StringUtils.isNotBlank(query.getCancelSubscribeStartTime()), WxMpFansDO::getCancelSubscribeTime, query.getCancelSubscribeStartTime(), query.getCancelSubscribeEndTime())
        ;
        List<WxMpFansDO> list = wxMpFansMapper.selectList(queryWrapper);
        if (!Collections3.isEmpty(list)) {
            return list.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public WxMpFansBO queryByFansId(Long id) {
        return BeanUtil.convertBean(wxMpFansMapper.selectById(id), WxMpFansBO.class);
    }

    private IWxMpFansService getBean() {
        return SpringBeanUtil.getBean(IWxMpFansService.class);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateAllFansSendCount(String appId) {
        return this.wxMpFansMapper.updateAllFansSendCount(appId) > 0;
    }

    /**
     * 根据openIds批量更新发送次数
     *
     * @param fansDOS
     * @param batch
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateFansSendCountByIdsBatch(List<WxMpFansDO> fansDOS, int batch) {
        if (Collections3.isEmpty(fansDOS)) {
            return false;
        }
        if (batch < 1) {
            batch = 1000;
        }
        int page = (fansDOS.size() - 1) / batch - 1;
        int min = 0;
        for (int i = 0; i < page; i++) {
            List<Long> ids = fansDOS.stream().skip(min).limit(batch).map(id -> id.getId()).collect(Collectors.toList());
            this.wxMpFansMapper.updateFansSendCountByIdsBatch(ids);
            min = min + batch;
        }
        return true;
    }

    @Override
    public List<WxMpFansIdBO> queryFansId(WxMpFansPageQuery query) {
        LambdaQueryWrapper<WxMpFansDO> queryWrapper = wrapperQueryCondition(query);
        queryWrapper.select(WxMpFansDO::getOpenId, WxMpFansDO::getId, WxMpFansDO::getSendCount);
        List<WxMpFansDO> list = wxMpFansMapper.selectList(queryWrapper);
        if (!Collections3.isEmpty(list)) {
            return JsonUtils.jsonToList(list, WxMpFansIdBO.class);
        }
        return Collections3.emptyList();
    }

    @Override
    public WxMpFansBO queryByOpenId(String openId) {
        WxMpFansDO wxMpFansDO = wxMpFansMapper.selectOne(new LambdaQueryWrapper<>(WxMpFansDO.class).eq(WxMpFansDO::getOpenId, openId));
        return BeanUtil.convertBean(wxMpFansDO, WxMpFansBO.class);
    }

    @Override
    public WxMpFansBO queryByAppIdAndOpenId(String appId, String openId) {
        WxMpFansDO wxMpFansDO = wxMpFansMapper.selectOne(new LambdaQueryWrapper<>(WxMpFansDO.class)
                .eq(WxMpFansDO::getOpenId, openId).eq(WxMpFansDO::getAppId, appId));
        return BeanUtil.convertBean(wxMpFansDO, WxMpFansBO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(WxMpFansDO wxMpFansDO) {
        wxMpFansDO.setCreateTime(LocalDateTime.now());
        wxMpFansDO.setModifyTime(LocalDateTime.now());
        return wxMpFansMapper.insert(wxMpFansDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modifyInfo(WxMpFansDO wxMpFansDO) {
        wxMpFansDO.setModifyTime(LocalDateTime.now());
        return wxMpFansMapper.updateById(wxMpFansDO) > 0;
    }

    @Override
    public List<String> subscribeQuery(SubscribeQuery query) {
        //未关注
        Integer subscribe = 0;
        if (null != query.getSubscribe() && query.getSubscribe()) {
            //关注
            subscribe = 1;
        }
        List<WxMpFansDO> wxMpFansDos = wxMpFansMapper.selectList(new LambdaQueryWrapper<>(WxMpFansDO.class)
                .eq(WxMpFansDO::getSubscribe, subscribe)
        );
        if (Collections3.isEmpty(wxMpFansDos)) {
            return Collections3.emptyList();
        }
        return wxMpFansDos.stream().map(WxMpFansDO::getOpenId).distinct().collect(Collectors.toList());
    }

    @Override
    public List<String> queryOpenIds(List<String> unionIds) {
        if (Collections3.isEmpty(unionIds)) {
            return Collections3.emptyList();
        }
        List<WxMpFansDO> wxMpFansDos = wxMpFansMapper.selectList(new LambdaQueryWrapper<>(WxMpFansDO.class)
                .in(WxMpFansDO::getUnionId, unionIds)
        );
        return wxMpFansDos.stream().map(WxMpFansDO::getOpenId).distinct().collect(Collectors.toList());
    }

    /**
     * 封装查询条件
     *
     * @param query
     * @return
     */
    private LambdaQueryWrapper<WxMpFansDO> wrapperQueryCondition(WxMpFansPageQuery query) {
        if (StringUtils.isNotBlank(query.getSubscribeStartTime()) || StringUtils.isNotBlank(query.getSubscribeEndTime())) {
            if (StringUtils.isBlank(query.getSubscribeStartTime())) {
                query.setSubscribeStartTime(LocalDate.now().toString());
            }
            if (StringUtils.isBlank(query.getSubscribeEndTime())) {
                query.setSubscribeEndTime(LocalDate.now().toString());
            }
        }

        if (StringUtils.isNotBlank(query.getCancelSubscribeStartTime()) || StringUtils.isNotBlank(query.getCancelSubscribeEndTime())) {
            if (StringUtils.isBlank(query.getCancelSubscribeStartTime())) {
                query.setCancelSubscribeStartTime(LocalDate.now().toString());
            }
            if (StringUtils.isBlank(query.getCancelSubscribeStartTime())) {
                query.setCancelSubscribeEndTime(LocalDate.now().toString());
            }
        }
        List<Long> fansIds = Collections3.emptyList();
        if (null != query.getTagsId()) {
            fansIds = mpFansTagsServiceImpl.queryFansIdsByTagsId(query.getAppId(), query.getTagsId());
        }
        LambdaQueryWrapper<WxMpFansDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(BaseDO::getCreateTime)
                .eq(WxMpFansDO::getAppId, query.getAppId())
                .eq(null != query.getSubscribe(), WxMpFansDO::getSubscribe, query.getSubscribe())
                .eq(StringUtils.isNotBlank(query.getOpenId()), WxMpFansDO::getOpenId, query.getOpenId())
                .eq(StringUtils.isNotBlank(query.getUnionId()), WxMpFansDO::getUnionId, query.getUnionId())
                .eq(null != query.getSex(), WxMpFansDO::getSex, query.getSex())
                .eq(null != query.getGroupId(), WxMpFansDO::getGroupId, query.getGroupId())
                .eq(StringUtils.isNotBlank(query.getSubscribeScene()), WxMpFansDO::getSubscribeScene, query.getSubscribeScene())
                .like(StringUtils.isNotBlank(query.getNickName()), WxMpFansDO::getNickName, query.getNickName())
                .between(StringUtils.isNotBlank(query.getSubscribeStartTime()), WxMpFansDO::getSubscribeTime, query.getSubscribeStartTime(), query.getSubscribeEndTime())
                .between(StringUtils.isNotBlank(query.getCancelSubscribeStartTime()), WxMpFansDO::getCancelSubscribeTime, query.getCancelSubscribeStartTime(), query.getCancelSubscribeEndTime())
                .in(!Collections3.isEmpty(fansIds), BaseDO::getId, fansIds)
        ;
        return queryWrapper;
    }
}
